package com.thread.exe;

import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class LogService {
	private final BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
	private final LoggerThread loggerThread = new LoggerThread();
	private final PrintWriter writer;

	public LogService(PrintWriter writer) {
		this.writer = writer;
	}

	private boolean isShutdown;
	private int reservations;
	
	public void start() {
		loggerThread.start();
	}
	
	public void stop() {
		synchronized (this) {
			isShutdown = true;
			loggerThread.interrupt();
		}
	}
	
	public void log(String msg) throws InterruptedException {
		synchronized (this) {
			if(isShutdown)
				throw new IllegalStateException();
			++reservations;
		}
		queue.put(msg);
	}
	
	@SuppressWarnings("unused")
	boolean checkMail(Set<String> hosts, long timeout, TimeUnit unit) throws InterruptedException {
		ExecutorService exec = Executors.newCachedThreadPool();
		final AtomicBoolean hasNewMail = new AtomicBoolean(false);
		try {
			for (String host : hosts) {
				exec.execute(new Runnable() {
					@Override
					public void run() {
						//
					}
				});
			}
		} finally {
			exec.shutdown();
			exec.awaitTermination(timeout, unit);
		}
		return hasNewMail.get();
	}
	
	private class LoggerThread extends Thread {
		@Override
		public void run() {
			try {
				while(true) {
					try {
						synchronized (LogService.this) {
							if(isShutdown && reservations == 0)
								break;
						}
						String msg = queue.take();
						synchronized (LogService.this) {
							reservations --;
						}
						writer.println(msg);
					} catch (InterruptedException e) {
						//retry
					}
				}
			} finally {
				writer.close();
			}
		}
	}
}
